Effect Lint Rules
Video Summary
Suppose we have the following code:
function App() { const [count, setCount] = React.useState(0);
React.useEffect(() => { console.log(count); }, []);
return ( <> <p>The count is: {count}</p> <button onClick={() => setCount(count + 1)}> Increment </button> </> );}
If we try to run this code, we'll get a lint warning from React, telling us we're violating an ESLint rule: react-hooks/exhaustive-deps
.
This is one of the most common rules to trip over, and the internet is full of folks trying to understand how to fix it. Unfortunately, one of the most common solutions is to disable the warning, rather than fixing it:
React.useEffect(() => { console.log(count); // eslint-disable-next-line}, []);
This magical incantation will silence the warning, but it doesn't solve the problem!
This rule isn't arbitrary, it's here for a very good reason: if we don't include the count
state variable in the dependency array, we'll wind up in an extremely confusing situation.
Every time we re-render, by calling setCount
, we take a new snapshot, and create a new count
variable. This means that there are different "versions" of the count
variable, one for each snapshot.
By not including count
in the dependency array, it means that our effect is "frozen in time"; the console.log(count)
code inside the effect only has access to the first count
variable, the one equal to 0
.
It leads to this bewildering situation, when the state changes:
function App() { // This `count` is equal to 3: const [count, setCount] = React.useState(0);
React.useEffect(() => { // This `count` is equal to 0: console.log(count); }, []);
return ( <> {/* this `count` is equal to 3: */} <p>The count is: {count}</p> <button onClick={() => setCount(count + 1)}> Increment </button> </> );}
Our effect has gotten out-of-sync with the rest of the code, and it means that we're seeing multiple versions of the state at the same time. This hurts my brain.
To fix it, we need to add count
to the dependency array:
React.useEffect(() => { console.log(count);}, [count]);
This means that the effect will re-run whenever we call setCount
, keeping it in sync as the state changes.
Here's the sandbox + memory visualization from the video:
Code Playground
Lint Warning
React Hook React.useEffect has a missing dependency: 'count'. Either include it or remove the dependency array.
Rule: react-hooks/exhaustive-deps
Location: Line 8, Column 6
- 0
Computer Memory